summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2022-10-07 05:42:15 +0200
committerGitHub <noreply@github.com>2022-10-07 05:42:15 +0200
commit61883d8820c057259c6c6113934a44f69742164c (patch)
treeeaae02f36b56101035ec9f79fc008ec0e2d2a938
parentMerge pull request #8944 from Tachi107/patch-2 (diff)
parentprogram_metadata: Unpack FileAccessHeader and FileAccessControl (diff)
downloadyuzu-61883d8820c057259c6c6113934a44f69742164c.tar
yuzu-61883d8820c057259c6c6113934a44f69742164c.tar.gz
yuzu-61883d8820c057259c6c6113934a44f69742164c.tar.bz2
yuzu-61883d8820c057259c6c6113934a44f69742164c.tar.lz
yuzu-61883d8820c057259c6c6113934a44f69742164c.tar.xz
yuzu-61883d8820c057259c6c6113934a44f69742164c.tar.zst
yuzu-61883d8820c057259c6c6113934a44f69742164c.zip
-rw-r--r--src/core/file_sys/program_metadata.cpp52
-rw-r--r--src/core/file_sys/program_metadata.h14
2 files changed, 51 insertions, 15 deletions
diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp
index e0cdf3520..08d489eab 100644
--- a/src/core/file_sys/program_metadata.cpp
+++ b/src/core/file_sys/program_metadata.cpp
@@ -33,11 +33,55 @@ Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {
return Loader::ResultStatus::ErrorBadACIHeader;
}
- if (sizeof(FileAccessControl) != file->ReadObject(&acid_file_access, acid_header.fac_offset)) {
+ // Load acid_file_access per-component instead of the entire struct, since this struct does not
+ // reflect the layout of the real data.
+ std::size_t current_offset = acid_header.fac_offset;
+ if (sizeof(FileAccessControl::version) != file->ReadBytes(&acid_file_access.version,
+ sizeof(FileAccessControl::version),
+ current_offset)) {
+ return Loader::ResultStatus::ErrorBadFileAccessControl;
+ }
+ if (sizeof(FileAccessControl::permissions) !=
+ file->ReadBytes(&acid_file_access.permissions, sizeof(FileAccessControl::permissions),
+ current_offset += sizeof(FileAccessControl::version) + 3)) {
+ return Loader::ResultStatus::ErrorBadFileAccessControl;
+ }
+ if (sizeof(FileAccessControl::unknown) !=
+ file->ReadBytes(&acid_file_access.unknown, sizeof(FileAccessControl::unknown),
+ current_offset + sizeof(FileAccessControl::permissions))) {
return Loader::ResultStatus::ErrorBadFileAccessControl;
}
- if (sizeof(FileAccessHeader) != file->ReadObject(&aci_file_access, aci_header.fah_offset)) {
+ // Load aci_file_access per-component instead of the entire struct, same as acid_file_access
+ current_offset = aci_header.fah_offset;
+ if (sizeof(FileAccessHeader::version) != file->ReadBytes(&aci_file_access.version,
+ sizeof(FileAccessHeader::version),
+ current_offset)) {
+ return Loader::ResultStatus::ErrorBadFileAccessHeader;
+ }
+ if (sizeof(FileAccessHeader::permissions) !=
+ file->ReadBytes(&aci_file_access.permissions, sizeof(FileAccessHeader::permissions),
+ current_offset += sizeof(FileAccessHeader::version) + 3)) {
+ return Loader::ResultStatus::ErrorBadFileAccessHeader;
+ }
+ if (sizeof(FileAccessHeader::unk_offset) !=
+ file->ReadBytes(&aci_file_access.unk_offset, sizeof(FileAccessHeader::unk_offset),
+ current_offset += sizeof(FileAccessHeader::permissions))) {
+ return Loader::ResultStatus::ErrorBadFileAccessHeader;
+ }
+ if (sizeof(FileAccessHeader::unk_size) !=
+ file->ReadBytes(&aci_file_access.unk_size, sizeof(FileAccessHeader::unk_size),
+ current_offset += sizeof(FileAccessHeader::unk_offset))) {
+ return Loader::ResultStatus::ErrorBadFileAccessHeader;
+ }
+ if (sizeof(FileAccessHeader::unk_offset_2) !=
+ file->ReadBytes(&aci_file_access.unk_offset_2, sizeof(FileAccessHeader::unk_offset_2),
+ current_offset += sizeof(FileAccessHeader::unk_size))) {
+ return Loader::ResultStatus::ErrorBadFileAccessHeader;
+ }
+ if (sizeof(FileAccessHeader::unk_size_2) !=
+ file->ReadBytes(&aci_file_access.unk_size_2, sizeof(FileAccessHeader::unk_size_2),
+ current_offset + sizeof(FileAccessHeader::unk_offset_2))) {
return Loader::ResultStatus::ErrorBadFileAccessHeader;
}
@@ -152,9 +196,7 @@ void ProgramMetadata::Print() const {
LOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.is_retail ? "YES" : "NO");
LOG_DEBUG(Service_FS, "Title ID Min: 0x{:016X}", acid_header.title_id_min);
LOG_DEBUG(Service_FS, "Title ID Max: 0x{:016X}", acid_header.title_id_max);
- u64_le permissions_l; // local copy to fix alignment error
- std::memcpy(&permissions_l, &acid_file_access.permissions, sizeof(permissions_l));
- LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", permissions_l);
+ LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", acid_file_access.permissions);
// Begin ACI0 printing (actual perms, unsigned)
LOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data());
diff --git a/src/core/file_sys/program_metadata.h b/src/core/file_sys/program_metadata.h
index e8fb4e27f..2e8960b07 100644
--- a/src/core/file_sys/program_metadata.h
+++ b/src/core/file_sys/program_metadata.h
@@ -144,20 +144,18 @@ private:
static_assert(sizeof(AciHeader) == 0x40, "ACI0 header structure size is wrong");
-#pragma pack(push, 1)
-
+ // FileAccessControl and FileAccessHeader need loaded per-component: this layout does not
+ // reflect the real layout to avoid reference binding to misaligned addresses
struct FileAccessControl {
u8 version;
- INSERT_PADDING_BYTES(3);
+ // 3 padding bytes
u64_le permissions;
std::array<u8, 0x20> unknown;
};
- static_assert(sizeof(FileAccessControl) == 0x2C, "FS access control structure size is wrong");
-
struct FileAccessHeader {
u8 version;
- INSERT_PADDING_BYTES(3);
+ // 3 padding bytes
u64_le permissions;
u32_le unk_offset;
u32_le unk_size;
@@ -165,10 +163,6 @@ private:
u32_le unk_size_2;
};
- static_assert(sizeof(FileAccessHeader) == 0x1C, "FS access header structure size is wrong");
-
-#pragma pack(pop)
-
Header npdm_header;
AciHeader aci_header;
AcidHeader acid_header;